import axios from 'axios';
import { message } from 'antd';
import commonErrorMsg, { httpFailMsg, commonErrMsg } from './error-msg';
import { getStorage, handleRequestPath } from '../../biz/index';
import uiData from '@store/ui-data';
import idempotentFn from './idempotent';
import notNeedRequestIdList from './notNeedRequestIdList';

const logoutList = [16021];
interface AjaxParams {
    url: string;
    method?: 'post' | 'get';
    data?: Record<string, unknown>;
    headers?: Record<string, unknown>;
    showErrorBySelf?: boolean;
    showLoading?: boolean;
    errMsg?: Record<string, string>;
    params?: Record<string, unknown>;
    timeout?: number;
}
export interface DoRequestParam {
    apiItem: ApiItem;
    data?: Record<string, unknown>;
    showErrorBySelf?: boolean;
    showLoading?: boolean;
    method?: 'post' | 'get';
    timeout?: number;
}

//不提示错误
const notShowErrorList = [91201];

/*
  {
    apiItem (path、errMsg基本配置)     必填
    data                              选填，默认 {}
    showErrorBySelf                   选填,默认 false
    showLoading                       选填,默认 true
  }
*/

export const doRequest = ({ apiItem, data = {}, method = 'post', showErrorBySelf = false, showLoading = true }: DoRequestParam): RequestReturnType => {
    const { path, errMsg, useMock = false } = apiItem;
    //这里定义模块名称
    return ajax({
        url: handleRequestPath(path, useMock),
        errMsg,
        data,
        method,
        showErrorBySelf,
        showLoading,
    });
};

let instance = axios.create({
    method: 'post',
    headers: {
        Accept: 'application/json',
        'Content-Type': 'application/json',
    },
});

//'/mock/captcha'
instance = idempotentFn(instance, { notNeedRequestIdList: notNeedRequestIdList });

/*
@param params:{
  url:[必填],请求地址
  method:[选填,默认POST;
  data:[选填]，根据get/post 默认[]/{} ,请求参数,
  showErrorBySelf:[选填]，默认true  当请求出错时,是否弹出错误提示
  headers:{.....}
  errMsg:{
    returnCode:'xxxx tip'
  }
}
*/

export const ajax = (ajaxParam: AjaxParams): Promise<Response> => {
    const { showErrorBySelf = false, data = {}, url, errMsg = {}, showLoading = true, method, timeout } = ajaxParam;
    const headers: Record<string, any> = data.headers || {};
    delete data.headers;
    let params = {};
    if (method === 'get') {
        params = data;
    }
    const axiosConfig = {
        data,
        params,
        url,
        headers: {
            'X-Access-Token': getStorage('token'),
            ...headers,
        },
        method,
        timeout: timeout || 60 * 1000,
    };
    showLoading && uiData.addLoadingNum(1);

    return instance
        .request(axiosConfig)
        .then((res) => {
            const { data: response, status } = res;
            if (response) {
                const { returnCode, data } = response;
                if (returnCode % 1000 === 0) {
                    //交给页面处理数据,没有错误，直接data
                    return Promise.resolve(data);
                } else {
                    //内部报错
                    if (showErrorBySelf) {
                        //交给页面处理错误，有错误码层
                        return Promise.resolve(response);
                    } else {
                        //业务报错
                        return ajaxBizError(response, errMsg);
                    }
                }
            } else {
                return showForHttpError(status);
            }
        })
        .catch((e) => {
            return showForHttpError(e);
        })
        .finally(() => {
            //更新requestId
            showLoading && uiData.addLoadingNum(-1);
        });
};

const showForHttpError = (e) => {
    if (e?.errorType === 'bizError') {
        //是业务报错，前面已经处理过
        return Promise.reject(e);
    }
    message.error({
        content: httpFailMsg,
        key: 'httpFailMsg',
    });
    return Promise.reject();
};

const ajaxBizError = (response, errMsg) => {
    /*
    服务端业务错误；
    根据 retrunCode 报错统一处理
    错误提示内容提取顺序: 对应api错误码配置=>前端通用错误码配置=>后端描述=>默认提示
    */
    const returnCode = response.returnCode || 'bizError';
    const errorTxt = errMsg[returnCode] || commonErrorMsg[returnCode] || response.returnDesc || commonErrMsg;
    //错误配置，与后端达成一致的配置错误提示
    if (!notShowErrorList.includes(returnCode)) {
        message.error({
            content: errorTxt,
            key: returnCode,
        });
    }

    if (logoutList.includes(returnCode)) {
        location.hash = '/login';
    }

    return Promise.reject({ errorType: 'bizError' });
};

export const fileUpload = (url: string, data): Promise<Response> => {
    const formData = new FormData();
    formData.append('file', data); // 'file' 是文件字段的名称，file 是要上传的文件
    const path = handleRequestPath(url, false);
    const headers = {
        'Content-Type': 'multipart/form-data', // 设置请求的 Content-Type 为 multipart/form-data
        'X-Access-Token': getStorage('token'), // 在请求头中添加 Authorization 字段，其中 token 是你的授权令牌
        'wx-gw-target-system': 'Rabia',
    };
    // 发送上传请求
    return axios.post(path, formData, { headers });
};

export default ajax;
